package com.wiscamp.ninechapters.problems.application.services;

import com.wiscamp.ninechapters.problems.application.assemblers.RegroupRuleAssembler;
import com.wiscamp.ninechapters.problems.application.dto.commands.sets.CreateRegroupRuleCommand;
import com.wiscamp.ninechapters.problems.application.dto.commands.sets.UpdateRegroupRuleCommand;
import com.wiscamp.ninechapters.problems.application.dto.vo.sets.RegroupRuleVO;
import com.wiscamp.ninechapters.problems.domain.repositories.RegroupRuleRepository;
import com.wiscamp.ninechapters.problems.domain.services.RegroupRuleService;
import cube.common.core.CollectionUtils;
import cube.ddd.application.BaseAppService;
import cube.ddd.application.command.DeleteCommand;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.common.query.PagedObjects;
import cube.ddd.common.query.PagedQuery;
import cube.ddd.utils.AppServiceUtils;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.springframework.stereotype.Service;

import java.util.Collection;

@Service
public class RegroupRuleAppService extends BaseAppService {

    private final RegroupRuleRepository regroupRuleRepository;
    private final RegroupRuleService regroupRuleService;

    public RegroupRuleAppService(RegroupRuleRepository regroupRuleRepository, RegroupRuleService regroupRuleService) {
        this.regroupRuleRepository = regroupRuleRepository;
        this.regroupRuleService = regroupRuleService;
    }

    @HandleServiceException
    public RegroupRuleVO getRegroupRule(@Min(0) long ruleId) {
        return AppServiceUtils.getById(ruleId, regroupRuleRepository::getRegroupRule,
                RegroupRuleAssembler.Instance::toRegroupRuleVO);
    }

    @HandleServiceException
    public Collection<RegroupRuleVO> getRegroupRulesByOrganization(@Min(0) long organizationId) {
        return AppServiceUtils.getListById(organizationId, regroupRuleRepository::getRegroupRulesByOrganization,
                RegroupRuleAssembler.Instance::toRegroupRuleVO);
    }

    @HandleServiceException
    public Collection<RegroupRuleVO> getRulesByCreator(@Min(0) long creatorId) {
        return AppServiceUtils.getListById(creatorId, regroupRuleRepository::getRulesByCreator,
                RegroupRuleAssembler.Instance::toRegroupRuleVO);
    }

    @HandleServiceException
    public RegroupRuleVO getRegroupRuleByCode(@NotBlank String ruleCode, @Min(0) long organizationId) {
        return AppServiceUtils.getByTextAndId(ruleCode, organizationId, regroupRuleRepository::getRegroupRuleByCode,
                RegroupRuleAssembler.Instance::toRegroupRuleVO);
    }

    @HandleServiceException
    public Collection<RegroupRuleVO> getRegroupRulesByName(@NotBlank String ruleName, @Min(0) long organizationId) {
        return AppServiceUtils.getListByTextAndId(ruleName, organizationId, regroupRuleRepository::getRegroupRulesByName,
                RegroupRuleAssembler.Instance::toRegroupRuleVO);
    }

    @HandleServiceException
    public Collection<RegroupRuleVO> getRegroupRulesByCode(@NotBlank String ruleCode, @Min(0) long organizationId) {
        return AppServiceUtils.getListByTextAndId(ruleCode, organizationId, regroupRuleRepository::getRegroupRulesByCode,
                RegroupRuleAssembler.Instance::toRegroupRuleVO);
    }

    @HandleServiceException
    public PagedObjects<RegroupRuleVO> getRegroupRulesByQuery(@NotNull PagedQuery query) {
        var pagedEntity = regroupRuleRepository.getRegroupRulesByQuery(query);
        return AppServiceUtils.convertPagedObjects(pagedEntity, RegroupRuleAssembler.Instance::toRegroupRuleVO);

    }

    @HandleServiceException
    public Collection<RegroupRuleVO> getSpecialPracticeRules(@NotBlank String gradeLevel) {
        var rules = regroupRuleRepository.getSpecialPracticeRules(gradeLevel);
        return CollectionUtils.toArrayList(rules, RegroupRuleAssembler.Instance::toRegroupRuleVO);
    }

    @HandleServiceException
    public RegroupRuleVO createRegroupRule(@NotNull CreateRegroupRuleCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.createOrUpdateBy(command, command.getOperatorId(), regroupRuleService::createRegroupRule,
                RegroupRuleAssembler.Instance::toRegroupRuleVO, RegroupRuleAssembler.Instance::fromCreateCommand);

    }

    @HandleServiceException
    public RegroupRuleVO updateRegroupRule(@NotNull UpdateRegroupRuleCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.createOrUpdateBy(command, command.getOperatorId(), regroupRuleService::updateRegroupRule,
                RegroupRuleAssembler.Instance::toRegroupRuleVO, RegroupRuleAssembler.Instance::fromUpdateCommand);
    }

    @HandleServiceException
    public boolean deleteRegroupRule(@NotNull DeleteCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.delete(command.getId(), command.getOperatorId(), regroupRuleService::deleteRegroupRule);
    }
}
